const utils = require('./utils.js');
const Config = require('./config.js');
const { Responses } = require('./responses.js');
const { Application } = require('./application.js');
const { FormSchemaValidator } = require('./form-schema-validator.js');
const { getLogger } = require('./logging.js');
const { getValidator } = require('./request-validator.js');

const logger = getLogger(Config.LOG_LEVEL);

class IngestApplicationLambda {
  static async handle (event, context) {
    logger.debug(`Executing ingest application lambda with
      context:  ${JSON.stringify(context)} for event:  ${JSON.stringify(event)}`
    );

    const body = JSON.parse(utils.getValueWithDefault(event, 'body', '{}'));
    const requestValidator = getValidator(body);
    let valid = false;

    try {
      valid = await requestValidator.check();
    } catch (error) {
      logger.error(`Unexpected error occurred validating request. ${error}`);
      return Responses.serverError({
        'errors': [
          {
            'message': 'An unexpected error occurred validating request.'
          }
        ]
      });
    }

    if (!valid) {
      logger.error(`Invalid request received.  Errors: ${JSON.stringify(requestValidator.errors)}`);

      return Responses.badRequest({
        'errors': [
          {
            'message': 'Invalid request received.',
            'detail': requestValidator.errors
          }
        ]
      });
    }

    const forms = utils.getValueWithDefault(body, 'forms', []);
    const formValidator = new FormSchemaValidator(forms);

    try {
      valid = await formValidator.check();
    } catch (error) {
      logger.error(`Unexpected error occurred validating schema. ${error}`);
      return Responses.serverError({
        'errors': [
          {
            'message': 'An unexpected error occurred validating schema.'
          }
        ]
      });
    }

    if (!valid) {
      logger.error(`Invalid forms received.  Errors: ${JSON.stringify(formValidator.errors)}`);
      return Responses.badRequest({
        'errors': [
          {
            'message': 'Invalid form(s) received.',
            'detail': formValidator.errors
          }
        ]
      });
    }

    const clientName = utils.getValueWithDefault(event, 'requestContext.authorizer.claims.scope', 'undefined').split('/')[0];
    const clientId = utils.getValueWithDefault(event, 'requestContext.authorizer.claims.client_id', 'undefined');
    const eventSource = utils.getValueWithDefault(context, 'functionName', 'undefined');

    const applicationDocument = utils.getValueWithDefault(body, 'application', '');
    const receivedDateTime = utils.getValueWithDefault(body, 'receivedDateTimestamp', '');
    const submittingPartner = utils.getValueWithDefault(body, 'submittingPartner', '');

    const application = new Application(
      applicationDocument,
      clientName,
      clientId,
      receivedDateTime,
      submittingPartner,
      forms,
      eventSource
    );

    try {
      await application.commit();
    } catch (error) {
      logger.error(`An unexpected error occurred committing request. ${error}`);
      return Responses.serverError({
        'errors': [
          {
            'message': 'An unexpected error occurred committing request.'
          }
        ]
      });
    }

    return Responses.accepted({
      'status': 'Received',
      'applicationId': application.applicationId
    });
  }
}

exports.handler = IngestApplicationLambda.handle;
